/**
 * 
 */
package com.gcgt.server.trader;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.math.stat.StatUtils;
import org.apache.commons.math.util.ResizableDoubleArray;

import com.gcgt.shared.trader.HistoryItem;
import com.gcgt.shared.trader.TradingHistory;
import com.gcgt.shared.trader.TradingParameters;

/**
 * @author Vincentas
 *
 */
public class DonatasTrader implements Trader {

	private Portfolio portfolio = new Portfolio();
	
	private ResizableDoubleArray prices = new ResizableDoubleArray();
	
	private BigDecimal cash;
	
	private final int days;
	
	private final BigDecimal maxLossPercent;
	
	private final BigDecimal commision;
	
	private final BigDecimal depositPercent;
	
	private final TradingHistory history = new TradingHistory();
	
	
	private BigDecimal maxPrice = BigDecimal.ZERO;
	
	public DonatasTrader(TradingParameters parameters) {
		this(
				parameters.getCash(),
				parameters.getDepositPercent(),
				parameters.getDays(),
				parameters.getMaxLossPercent(),
				parameters.getCommision());
	}
	
	public DonatasTrader(BigDecimal cash, BigDecimal depositPercent, int days, BigDecimal maxLossPercent, BigDecimal commision) {
		this.cash = cash;
		this.depositPercent = depositPercent;
		this.commision = commision;
		this.days = days;
		this.maxLossPercent = maxLossPercent;
	}
	
	@Override
	public void marketUpdate(Market market) {
		MarketUpdate update = market.getTicker("OPT");
		
		if (prices.getNumElements() >= days) {
			prices.addElementRolling(update.getOpen().doubleValue());
		} else {
			prices.addElement(update.getOpen().doubleValue());
		}
		
		if (update.getOpen().compareTo(maxPrice) > 0) {
			maxPrice = update.getOpen();
		}
		
		if (maxPrice.subtract(update.getOpen()).compareTo(maxPrice.multiply(maxLossPercent)) > 0) {
			List<Position> positionsToSell = new ArrayList<Position>(portfolio.getPositions(update.getTicker()));
			market.sell(this, positionsToSell, new PayCallback() {
			});
		}		
	
		if (StatUtils.mean(prices.getElements()) > update.getOpen().doubleValue()) {
			maxPrice = update.getOpen();
			market.buy(this, update.getTicker(), getAvailableCash(), new PayCallback() {
			});
		}
		
		HistoryItem historyItem = new HistoryItem();
		historyItem.setDate(update.getDate());
		historyItem.setCash(getCash());		
		historyItem.setTotal(getCash().add(getPortfolio().getValue(update)));
		
		history.add(historyItem);
		
	}
	
	private BigDecimal getAvailableCash() {
		return cash.subtract(portfolio.getValue().multiply(new BigDecimal(0.1)));
	}
	
	private void buy(MarketUpdate update) {

	}
	
	private void sell(MarketUpdate update, Position position, BigDecimal price) {
		cash = cash.add(price.multiply(new BigDecimal(position.getAmount())).multiply(depositPercent));
		cash = cash.subtract(commision);
		portfolio.removePosition(position);
	}
	
	/**
	 * @return the commision
	 */
	public BigDecimal getCommision() {
		return commision;
	}

	@Override
	public Portfolio getPortfolio() {
		return portfolio;
	}

	/**
	 * @return the cash
	 */
	public BigDecimal getCash() {
		return cash.setScale(2, BigDecimal.ROUND_HALF_UP);
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return getPortfolio() + " Cash " + getCash().setScale(2, BigDecimal.ROUND_HALF_UP) + " Total : " + getPortfolio().getValue().add(getCash()).setScale(2, BigDecimal.ROUND_HALF_UP);
	}

	@Override
	public TradingHistory getHistory() {
		return history;
	}

}
